/**
* 版权声明：厦门睿商网络科技有限公司 版权所有 违者必究
* 日    期：2020-05-25
*/
package com.rzico.order.controller.admin;

import com.alibaba.fastjson.JSON;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.rzico.annotation.Log;
import com.rzico.base.BaseController;
import com.rzico.base.CommResult;
import com.rzico.basics.entity.Enterprise;
import com.rzico.basics.entity.Product;
import com.rzico.basics.entity.Shop;
import com.rzico.basics.service.EnterpriseService;
import com.rzico.basics.service.ProductService;
import com.rzico.basics.service.ShopService;
import com.rzico.core.entity.SysEmployee;
import com.rzico.core.entity.SysOffice;
import com.rzico.core.entity.SysReport;
import com.rzico.core.entity.SysUser;
import com.rzico.core.service.SysEmployeeService;
import com.rzico.core.service.SysOfficeService;
import com.rzico.core.service.SysReportService;
import com.rzico.core.service.SysUserService;
import com.rzico.entity.PageResult;
import com.rzico.entity.Pageable;
import com.rzico.exception.CustomException;
import com.rzico.order.entity.Allocate;
import com.rzico.order.entity.AllocateItem;
import com.rzico.order.entity.Purchase;
import com.rzico.order.service.AllocateItemService;
import com.rzico.order.service.AllocateService;
import com.rzico.util.HttpUtils;
import com.rzico.util.StringUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import net.sf.jasperreports.engine.JRException;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 调拨单控制层
 *
 * @author Rzico Boot
 * @version 1.0
 * @date 2020-05-25
 */
@Api(description = "调拨单接口")
@RestController
@RequestMapping("/admin/allocate")
public class AllocateAdminController extends BaseController {

    @Value("${rzico.filePath.windows}")
    private String windowsFilePath;

    @Value("${rzico.filePath.linux}")
    private String linuxFilePath;

    @Autowired
    private AllocateService allocateService;

    @Autowired
    private AllocateItemService allocateItemService;

    @Autowired
    private SysOfficeService sysOfficeService;

    @Autowired
    private SysEmployeeService sysEmployeeService;

    @Autowired
    private ProductService productService;

    @Autowired
    private EnterpriseService enterpriseService;

    @Autowired
    private SysReportService sysReportService;

    @Autowired
    private ShopService shopService;

    @Autowired
    protected SysUserService sysUserService;

    /**
     * 分页查询调拨单
     *
     * @return
    */
    @ApiOperation("分页查询调拨单")
    @GetMapping("/list")
    @ApiImplicitParams({@ApiImplicitParam(name = "startDate", value = "开始时间", dataType = "String", paramType = "query") ,
            @ApiImplicitParam(name = "endDate", value = "结束时间", dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "sn", value = "调拨单号", dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "productId", value = "商品Id", dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "orderStatus", value = "单据状态(0、未确认 1、已确认、2、已完成 3、已取消)", dataType = "Integer", paramType = "query"),
            @ApiImplicitParam(name = "shippingStatus", value = "出入库状态(1、待出库 2、已出库 3、已入库)", dataType = "Integer", paramType = "query"),
            @ApiImplicitParam(name = "inShopId", value = "入库门店", dataType = "Integer", paramType = "query"),
            @ApiImplicitParam(name = "outShopId", value = "出库门店", dataType = "Integer", paramType = "query")
    })
    public CommResult<Allocate> list(Date startDate, Date endDate, String sn, Integer orderStatus,
                                     Integer shippingStatus, Integer inShopId, Integer outShopId, Long productId, Pageable pageable) {
        Map<String, Object> params = new HashMap<String, Object>();
        params = buildSortField(params, pageable);
        if (startDate!=null){
            params.put("startDate", DateUtils.truncate(startDate, Calendar.DATE));
        }
        if (endDate!=null){
            params.put("endDate", DateUtils.addMilliseconds(DateUtils.addDays(endDate,1),-1));
        }
        if (StringUtils.isNotEmpty(sn)){
            params.put("sn", sn);
        }
        if (null != orderStatus){
            params.put("orderStatus", orderStatus);
        }
        if (null != shippingStatus){
            params.put("shippingStatus", shippingStatus);
        }
        if (null != inShopId){
            params.put("inShopId", inShopId);
        }
        if (null != outShopId){
            params.put("outShopId", outShopId);
        }
        if (null != productId){
            Product product = productService.findById(productId);
            params.put("goodsId", product.getGoodsId());
        }

        params.put("deleted", false);


        Enterprise enterprise = enterpriseService.getCurrent();
        if (enterprise!=null) {
            params.put("enterpriseId", enterprise.getId());
        } else {
            return CommResult.error("没有开通企业");
        }


        //非管理员都启用数据权限
//        SysUser sysUser = sysUserService.getCurrent();
//        if (!sysUserService.isAdmin(sysUser)) {
//            params.put("dataScopeId",sysUser.getId());
//        }

        Page<Object> startPage = PageHelper.startPage(pageable.getPageNum(), pageable.getPageSize());
        List<Allocate> list = allocateService.selectList(params);
        PageResult<Allocate> pageResult = new PageResult<Allocate>(list, startPage.getTotal(), pageable);
        return CommResult.success(pageResult);
    }

    /**
     * 查询单条调拨单
     *
     * @return
    */
    @ApiOperation("查询单条调拨单")
    @GetMapping("/find/{id}")
    public CommResult<Allocate> find(@PathVariable Long id) {
        Allocate result = allocateService.findById(id);
        result.setItemList(allocateItemService.getItemList(id));

        Map<String,Object> data = new HashMap<>();
        if (result.getOfficeId()!=null && !"".equals(result.getOfficeId())) {
            SysOffice sysOffice = sysOfficeService.selectByPrimaryKey(result.getOfficeId());
            if (sysOffice!=null) {
                data.put("officeName", sysOffice.getName());
            } else {
                data.put("officeName", "无");
            }
        } else {
            data.put("officeName", "无");
        }
        if (result.getCreateBy()!=null) {
            SysEmployee sysUser = sysEmployeeService.selectByPrimaryKey(result.getCreateBy());
            if (sysUser!=null) {
                data.put("createByName", sysUser.getName());
            } else {
                data.put("createByName", "无");
            }
        } else {
            data.put("createByName", "无");
        }

        data.put("allocate",result);
        return CommResult.success(data);

    }

    /**
     * 保存调拨单
     *
     * @param allocate
     * @return
     */
    @ApiOperation("保存调拨单")
    @PostMapping("/save")
    public CommResult<Allocate> save(@RequestBody Allocate allocate) {
        Assert.notNull(allocate.getOutShopId(), "调出门店为空");
        Assert.notNull(allocate.getInShopId(), "调入门店为空");
        Assert.notNull(allocate.getItemList(), "调拨明细为空");

        int affectCount = allocateService.insertOrder(allocate);
        if (affectCount <= 0) {
            return CommResult.error();
        }
        Allocate result = allocateService.findById(allocate.getId());
        return CommResult.success(result);

    }


    /**
     * 批量删除调拨单
     *
     * @param ids
     * @return
     */
    @Log(desc = "批量删除调拨单", type = Log.LOG_TYPE.DEL)
    @ApiOperation("批量删除调拨单,ids用逗号拼接")
    @PostMapping("/del/{ids}")
    public CommResult<Allocate> del(@PathVariable String ids) {
        try {
            allocateService.deleteByIds(ids.split(","));
        } catch (Exception e) {
            return CommResult.error(e.getMessage());
        }

        return CommResult.success();
    }

    /**
     * 更新调拨单
     *
     * @param allocate
     * @return
     */
    @ApiOperation("更新调拨单")
    @PostMapping("/update")
    public CommResult<Allocate> update(@RequestBody Allocate allocate) {
        Assert.notNull(allocate.getId(), "ID为空");
        logger.info("更新调拨单传参：[{}]", allocate);
        int affectCount = allocateService.update(allocate);
        if (affectCount <= 0){
            return CommResult.error();
        }
        Allocate result = allocateService.findById(allocate.getId());
        return CommResult.success(result);
    }

    /**
     * 调拨单确认
     *
     * @param id
     * @return
     */
    @ApiOperation("调拨单确认")
    @PostMapping("/confirm/{id}")
    public CommResult<Allocate> confirm(@PathVariable Long id) {
        Assert.notNull(id, "订单编码为空");
        int affectCount = allocateService.confirm(id);
        if (affectCount <= 0){
            return CommResult.error();
        }
        Allocate result = allocateService.findById(id);
        return CommResult.success(result);
    }

    /**
     * 调拨出库
     *
     * @param id
     * @return
     */
    @ApiOperation("调拨出库")
    @PostMapping("/alloteOut/{id}")
    public CommResult<Allocate> alloteOut(@PathVariable Long id, @RequestBody List<AllocateItem> itemList) {
        Assert.notNull(itemList, "发货明细为空");
        String errMsg = "";
        for (AllocateItem allocateItem : itemList){
            if (null == allocateItem.getId()){
                errMsg = "商品明细ID为空";
                break;
            }
            if (null == allocateItem.getQuantity()){
                errMsg = "出库数量为空";
                break;
            }
        }
        if (StringUtils.isNotEmpty(errMsg)){
            return CommResult.error(errMsg);
        }

        int affectCount = allocateService.allocateOut(id, itemList);
        if (affectCount <= 0){
            return CommResult.error();
        }
        Allocate result = allocateService.findById(id);
        return CommResult.success(result);
    }


    /**
     * 调拨入库
     *
     * @param id
     * @return
     */
    @ApiOperation("调拨入库")
    @PostMapping("/alloteIn/{id}")
    public CommResult<Allocate> alloteIn(@PathVariable Long id, @RequestBody List<AllocateItem> itemList) {
        Assert.notNull(itemList, "入库明细为空");
        String errMsg = "";
        for (AllocateItem allocateItem : itemList){
            if (null == allocateItem.getId()){
                errMsg = "商品明细ID为空";
                break;
            }
            if (null == allocateItem.getQuantity()){
                errMsg = "入库数量为空";
                break;
            }
        }
        if (StringUtils.isNotEmpty(errMsg)){
            return CommResult.error(errMsg);
        }

        int affectCount = allocateService.allocateIn(id, itemList);
        if (affectCount <= 0){
            return CommResult.error();
        }
        Allocate result = allocateService.findById(id);
        return CommResult.success(result);
    }

    /**
     * 作废(已确认、未确认可以作废)
     * @param id
     * @return
     */
    @ApiOperation("作废")
    @PostMapping("/cancel/{id}")
    public CommResult<Allocate> cancel(@PathVariable Long id) {
        int affectCount = allocateService.cancel(id);
        if (affectCount <= 0){
            return CommResult.error();
        }
        Allocate result = allocateService.findById(id);
        return CommResult.success(result);
    }

    /**
     *  订单打印
     *
     * @param id
     * @return
     */
    @ApiOperation("打印")
    @GetMapping("/print/{id}")
    public void print(HttpServletRequest request, HttpServletResponse response, @PathVariable String id)
            throws ClassNotFoundException, SQLException, JRException, IOException, IllegalAccessException{
        logger.info(">>>>>>>>>>>>>>>>>>>>>>>>>>>订单打印 start<<<<<<<<<<<<<<<<<<<<<<<<<<<");
        Map<String, Object> param = new HashMap<String, Object>();
        param = HttpUtils.requestParam(request);

        Allocate allocate = allocateService.selectByPrimaryKey(id);
        if (null == allocate){
            throw new CustomException("调拨单不存在");
        }
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Enterprise enterprise = enterpriseService.selectByPrimaryKey(allocate.getEnterpriseId());
        if (null == enterprise) {
            throw new CustomException("没有开通企业");
        }
        SysOffice sysOffice = sysOfficeService.findById(allocate.getOfficeId());
        if (null != sysOffice){
            param.put("officeName",sysOffice.getOfficeName());
        }
        param.put("COMPANY",enterprise.getName());
        param.put("enterpriseId",enterprise.getId());
        param.put("orderDate", sdf.format(allocate.getOrderDate()));
        param.put("memo", allocate.getMemo());
        param.put("sn", allocate.getSn());

        Shop inShop = shopService.selectByPrimaryKey(allocate.getInShopId());
        Shop outShop = shopService.selectByPrimaryKey(allocate.getOutShopId());

        param.put("inShopName", inShop.getName());
        param.put("outShopName", outShop.getName());

        logger.info("打印报表查询参数：{}", param.toString());

        String fileName = enterprise.getMchId()+"_"+allocate.getSn() + ".jasper";
        //fileName就是sys_report表的id
        SysReport sysReport = sysReportService.selectByPrimaryKey(fileName);

        String filePath = "";
        if (System.getProperty("os.name").contains("Windows")) {
            filePath = windowsFilePath;
        } else if (System.getProperty("os.name").contains("Linux")) {
            filePath = linuxFilePath;
        }
        //检查服务器上是否存在模板
        File file = new File(filePath + File.separator + fileName);
        if (!file.exists()){
            try {
                String url = sysReport == null?"":sysReport.getTemplate();
                sysReportService.fileDownLoad(response, url, filePath, fileName);
            } catch (Exception e){
                logger.info("打印模板下载失败");
                throw new CustomException("打印模板下载失败");
            }
        }


        String reportName = "allocatePrint";
        param.put("REPORT_NAME","调拨单");
        StringBuffer sql = new StringBuffer();
        sql.append(" SELECT b.sn,b.name,b.spec,b.unit, ");
        sql.append("    b.price,b.quantity,round(b.price*b.quantity, 2) as amount, 0 as discount FROM wx_allocate_item b ");
        sql.append(" WHERE b.allocate_id = "+id);

        File file2 = new File(filePath + File.separator + fileName);
        if (!file2.exists()) {
            //下载之后还不存在，就使用classpath路径的模板
            sysReportService.ReportToPdfBySql(reportName, param, sql.toString(), response);
        }else{
            sysReportService.commReportToPdf(filePath, fileName, param, sql.toString(), response);
        }
    }


    /**
     *  订单打印
     *
     * @param id
     * @return
     */
    @ApiOperation("导出")
    @GetMapping("/export/{id}")
    public void export(HttpServletRequest request, HttpServletResponse response, @PathVariable String id)
            throws ClassNotFoundException, SQLException, JRException, IOException, IllegalAccessException{
        logger.info(">>>>>>>>>>>>>>>>>>>>>>>>>>>订单打印 start<<<<<<<<<<<<<<<<<<<<<<<<<<<");
        Map<String, Object> param = new HashMap<String, Object>();
        param = HttpUtils.requestParam(request);

        Allocate allocate = allocateService.selectByPrimaryKey(id);
        if (null == allocate){
            throw new CustomException("调拨单不存在");
        }
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Enterprise enterprise = enterpriseService.selectByPrimaryKey(allocate.getEnterpriseId());
        if (null == enterprise) {
            throw new CustomException("没有开通企业");
        }
        SysOffice sysOffice = sysOfficeService.findById(allocate.getOfficeId());
        if (null != sysOffice){
            param.put("officeName",sysOffice.getOfficeName());
        }
        param.put("COMPANY",enterprise.getName());
        param.put("enterpriseId",enterprise.getId());
        param.put("orderDate", sdf.format(allocate.getOrderDate()));
        param.put("memo", allocate.getMemo());
        param.put("sn", allocate.getSn());

        Shop inShop = shopService.selectByPrimaryKey(allocate.getInShopId());
        Shop outShop = shopService.selectByPrimaryKey(allocate.getOutShopId());
        param.put("inShopName", inShop.getName());
        param.put("outShopName", outShop.getName());

        logger.info("打印报表查询参数：{}", param.toString());

        String reportName = "allocatePrint";
        param.put("REPORT_NAME","调拨单");
        StringBuffer sql = new StringBuffer();
        sql.append(" SELECT b.sn,b.name,b.spec,b.unit, ");
        sql.append("    b.price,b.quantity,round(b.price*b.quantity, 2) as amount, 0 as discount FROM wx_allocate_item b ");
        sql.append(" WHERE b.allocate_id = "+id);
        sysReportService.ReportToExcelBySql(reportName, param, sql.toString(), response);
    }

}
